<!--
 * @Description: 可编辑的表单组件
-->

<template>
  <div class="editable-form">
    <el-form
      ref="formRef"
      :model="pageData.pageFormData"
      :rules="formRules"
      label-width="100px"
    >
      <div v-for="(row, index) in pageFormItems" :key="index" class="row">
        <el-form-item
          v-for="item in row"
          :key="item.prop"
          :label="item.label"
          :prop="item.prop"
          :class="item.class"
          :error="item.error"
        >
          <!-- 输入框 -->
          <el-input
            v-if="item.type === 'input'"
            v-model="pageData.pageFormData[item.prop]"
            :placeholder="item.placeholder"
            :clearable="item.clearable || true"
            :disabled="item.disabled || false"
            :maxlength="item.maxlength || 256"
            :size="formSize"
            :rows="item.rows || 3"
            class="width100"
            @change="item.change"
          />
          <!-- 下拉框 -->
          <el-select
            v-else-if="item.type === 'select'"
            v-model="pageData.pageFormData[item.prop]"
            :placeholder="item.placeholder"
            :clearable="item.clearable || true"
            :disabled="item.disabled || false"
            :filterable="item.filterable || true"
            :multiple="item.multiple || false"
            :size="formSize"
            class="width100"
            @change="item.change"
          >
            <el-option
              v-for="option in item.options"
              :key="option[item.valueStr]"
              :label="option[item.labelStr]"
              :value="option[item.valueStr]"
            />
          </el-select>
        </el-form-item>
      </div>
    </el-form>
  </div>
</template>

<script>
import { formSize } from "@/config";
export default {
  name: "EditableForm",
  components: {},
  props: {
    // 表单数据
    formData: {
      type: Object,
      required: true,
      default: () => {
        return {};
      },
    },
    // 表单项
    formItems: {
      type: Array,
      required: true,
      default: () => {
        return [];
      },
    },
    // 表单布局 每行展示多少个表单项
    formRows: {
      type: Array,
      required: true,
      default: () => {
        return [];
      },
    },
    formRules: {
      type: Object,
      default: () => {
        return {};
      },
    },
  },
  emits: [],
  setup(props) {
    /* 定义变量 */
    const store = useStore();
    // DOM
    const formRef = ref();
    // 界面变量
    const pageData = reactive({
      pageFormData: props.formData,
    });

    // 按照布局配置 组装表单项(一行几个)
    const pageFormItems = computed(() => {
      const tempData = [];
      // slice 遇到引用数据类型时是浅拷贝，但此处不会修改数组中的值，所以暂时没影响
      const tempFormItems = props.formItems
        .slice(0, props.formItems.length)
        .filter((item) => {
          return (
            !item.hasOwnProperty("isHidden") ||
            (typeof item.isHidden === "boolean" && !item.isHidden) ||
            (typeof item.isHidden === "function" &&
              !item.isHidden(item, props.formData[item.key]))
          );
        });
      props.formRows.forEach((rowItemQuantity) => {
        tempData.push(tempFormItems.splice(0, rowItemQuantity));
      });
      return tempData;
    });

    /**
     * @description: 表单校验方法
     * @param {*}
     * @return {*}
     */
    const checkFormData = () => {
      let isValid = false;
      unref(formRef).validate((valid) => {
        isValid = valid;
      });
      return isValid;
    };

    /**
     * 重置单项，将其值重置为初始值，并移除校验结果
     */
    const resetFields = () => {
      unref(formRef) && unref(formRef).resetFields();
    };
    /**
     * 移除表单校验，而且可以只对部分字段进行移除校验
     */
    const clearValidate = (name) => {
      unref(formRef) && unref(formRef).clearValidate(name);
    };

    /**
     * 校验某个表单项
     * @param fields String | Array
     * @param errorFun
     */
    const validateField = (fields, errorFun) => {
      unref(formRef) && unref(formRef).validateField(fields, errorFun);
    };
    /* 监听 */
    watch(
      () => props.formData,
      (newValue, oldValue) => {
        pageData.pageFormData = newValue;
      }
    );

    /* 返回 */
    return {
      pageData,
      formRef,
      pageFormItems,
      formSize,
    };
  },
};
</script>

<style lang="scss" scoped>
.editable-form {
  display: flex;
  flex-direction: column;
  width: 100%;
  .row {
    display: flex;
    flex-direction: row;
    .el-form-item {
      width: 25%;
      .el-form-item__content {
        width: calc(100% - 100px);
      }
    }
  }
}
.width100 {
  width: 100%;
}
</style>
